GetX 状态管理原理
GetBuilder
状态管理类注入
示例:Get.put(CommonState())
dart
extension Inst on GetInterface {
S put<S>(S dependency,
{String? tag,
bool permanent = false,
InstanceBuilderCallback<S>? builder}) =>
GetInstance().put<S>(dependency, tag: tag, permanent: permanent);
}
dart
class GetInstance {
static final Map<String, _InstanceBuilderFactory> _singl = {};
S put<S>(
S dependency, {
String? tag,
bool permanent = false,
@Deprecated("Do not use builder, it will be removed in the next update")
InstanceBuilderCallback<S>? builder,
}) {
//创建 _InstanceBuilderFactory,并添加到 _singl Map 中。
_insert(isSingleton: true, name: tag, permanent: permanent, builder: builder ?? (() => dependency));
return find<S>(tag: tag);
}
void _insert<S>({bool? isSingleton, String? name, bool permanent = false, required InstanceBuilderCallback<S> builder, bool fenix = false}) {
//key = name == null ? type.toString() : type.toString() + name;
final key = _getKey(S, name);
//是否已存在
if (_singl.containsKey(key)) {
final dep = _singl[key];
//已存在但已废弃,则创建新的并覆盖
if (dep != null && dep.isDirty) {
_singl[key] = _InstanceBuilderFactory<S>( isSingleton, builder, permanent, false, fenix, name, lateRemove: dep as _InstanceBuilderFactory<S>);
}
} else {
_singl[key] = _InstanceBuilderFactory<S>(isSingleton, builder, permanent, false, fenix, name);
}
}
S find<S>({String? tag}) {
//构建 key
final key = _getKey(S, tag);
//检测是否存在
if (isRegistered<S>(tag: tag)) {
//获取到 _InstanceBuilderFactory
final dep = _singl[key];
//...
//如果通过 put() 存入则标记 isInit = true,并根据 Get.smartManagement 与路由建立关联
final i = _initDependencies<S>(name: tag);
//返回 controller
return i ?? dep.getDependency() as S;
}
}
}
小结
- controller 管理的核心在 GetInstance 中,内部维护了一个名为 _singl 的 Map
- Map 的 key 由 controller 的类型和 tag 生成。
- 创建并注册成功后,调用 find() 返回注册的 controller。
GetBulder Widget
dart
class GetBuilder<T extends GetxController> extends StatefulWidget {
final GetControllerBuilder<T> builder;
final bool global; //true
final Object? id;
final String? tag;
final bool autoRemove; //true
final bool assignId; //false
final Object Function(T value)? filter;
final void Function(GetBuilderState<T> state)? initState,dispose,didChangeDependencies;
final void Function(GetBuilder oldWidget, GetBuilderState<T> state)? didUpdateWidget;
final T? init;
@override
GetBuilderState<T> createState() => GetBuilderState<T>();
}
class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> with GetStateUpdaterMixin {
bool? _isCreator = false;
@override
void initState() {
super.initState();
//调用注入的 initState()
widget.initState?.call(this);
//检测 controller 是否注册
// bool isRegistered<S>({String? tag}) => _singl.containsKey(_getKey(S, tag));
var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag);
//是否全局,默认 true
if (widget.global) {
if (isRegistered) {
//检测 controller 是否已就绪
// 当 controller isInit = false 时返回 true。
// _isCreator 用于在 dispose() 中判断是否需要从状态管理中移除
if (GetInstance().isPrepared<T>(tag: widget.tag)) {
_isCreator = true;
} else {
_isCreator = false;
}
controller = GetInstance().find<T>(tag: widget.tag);
} else {
//未注册,则将注入的 init(即 controller) 注册
controller = widget.init;
_isCreator = true;
GetInstance().put<T>(controller!, tag: widget.tag);
}
} else {
//非全局,则不注册,并调用 controller#onStart()
controller = widget.init;
_isCreator = true;
controller?.onStart();
}
//调用注入的 filter() 过滤 controller
if (widget.filter != null) {
_filter = widget.filter!(controller!);
}
_subscribeToController();
}
void _subscribeToController() {
//移除之前的监听
_remove?.call();
//根据是否注入 id 来区分监听。当有事件时最终都是执行 getUpdate(),该方法在 GetStateUpdaterMixin 中。
_remove = (widget.id == null)
? controller?.addListener(_filter != null ? _filterUpdate : getUpdate)
: controller?.addListenerId(widget.id, _filter != null ? _filterUpdate : getUpdate);
}
@override
void dispose() {
super.dispose();
//调用注入的 dispose()
widget.dispose?.call(this);
//检测 controller 是否已不再需要,若true则移除。
// _isCreator: 当 controller isInit = false 时为 true,即 controller 已不再使用.
// widget.assignId: 默认为 true
// widget.autoRemove: 默认为 true
if (_isCreator! || widget.assignId) {
if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
GetInstance().delete<T>(tag: widget.tag);
}
}
//移除监听
_remove?.call();
//重置状态
controller = null;
_isCreator = null;
_remove = null;
_filter = null;
}
@override
Widget build(BuildContext context) {
//执行注入的 builder(),返回 controller 并加载页面
return widget.builder(controller!);
}
}
mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> {
//如果 widget 已挂载,则调用 setState() 触发刷新
void getUpdate() {
if (mounted) setState(() {});
}
}
dart
//controller?.addListener()
//controller?.addListenerId()
mixin ListNotifierMixin on ListenableMixin {
List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[];
HashMap<Object?, List<GetStateUpdate>>? _updatersGroupIds = HashMap<Object?, List<GetStateUpdate>>();
@override
Disposer addListener(GetStateUpdate listener) {
_updaters!.add(listener);
return () => _updaters!.remove(listener);
}
Disposer addListenerId(Object? key, GetStateUpdate listener) {
_updatersGroupIds![key] ??= <GetStateUpdate>[];
_updatersGroupIds![key]!.add(listener);
return () => _updatersGroupIds![key]!.remove(listener);
}
}
小结
- GetBuilder Widget 在 initState() 阶段获取注入的状态管理类,若没有则创建(使用 init 入参注入的状态管理类)。调用 controller.addListener() 添加监听,若有事件发生则触发 setState() 刷新 GetBuilder Widget。
- GetBuilder Widget 在 dispose() 阶段注销监听和重置状态,并根据条件判断是否需要将 controller 销毁。
GetxController Upadte
dart
abstract class GetxController extends DisposableInterface with ListenableMixin, ListNotifierMixin {
void update([List<Object>? ids, bool condition = true]) {
if (!condition) {
return;
}
if (ids == null) {
refresh();
} else {
for (final id in ids) {
refreshGroup(id);
}
}
}
}
mixin ListNotifierMixin on ListenableMixin {
List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[];
HashMap<Object?, List<GetStateUpdate>>? _updatersGroupIds = HashMap<Object?, List<GetStateUpdate>>();
@protected
void refresh() {
//遍历_updaters 回调
_notifyUpdate();
}
@protected
void refreshGroup(Object id) {
//获取 _updatersGroupIds 中的 List,遍历回调
_notifyIdUpdate(id);
}
}
小结
在 GetxController 中调用 update(),根据是否传入 ids 触发不同的回调。该回调最终执行到 GetBuilder Widget 的监听。
小结
注意点:
- 如果手动设置了 global = false,则不校验和注册(put) controller,并在 GetBuilder$dispose() 时销毁(置为 null)。
- controller.addListener() 时区分是否传入 id,在 update() 时也会区分触发回调。
- update() 时直接执行 setState() 刷新 GetBuilder$builder 内容,所以需要控制刷新范围。
Obx
.box
示例: var count = 0.obx
dart
class RxInt extends Rx<int> {}
class Rx<T> extends _RxImpl<T> {}
abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> {
//将初始值赋值给 _value, RxObjectMixin 中
_RxImpl(T initial) {
_value = initial;
}
}
class RxNotifier<T> = RxInterface<T> with NotifyManager<T>;
//.obx 创建了一个 _RxImpl 对象,内部创建了 GetStream 对象,GetStream 可以理解为一个 Stream
mixin NotifyManager<T> {
GetStream<T> subject = GetStream<T>();
final _subscriptions = <GetStream, List<StreamSubscription>>{};
}
小结
- .box 最终实现是 _RxImpl<\T>,其继承自 RxNotifier,RxNotifier 混入了 NotifyManager,所以 _RxImpl 最终继承了 RxInterface 并混入了 NotifyManager 和 RxObjectMixin。
- _RxImpl 在创建的时候,由于混入 NotifyManager,所以也就创建了一个 GetStream。(此 Stream 将用于数据变更事件传输)
Obx Widget
示例:Obx(() => Text(controller.count.value))
dart
class Obx extends ObxWidget {
final WidgetCallback builder;
const Obx(this.builder, {Key? key}) : super(key: key);
@override
Widget build() => builder();
}
dart
abstract class ObxWidget extends StatefulWidget {
@override
ObxState createState() => ObxState();
@protected
Widget build();
}
class ObxState extends State<ObxWidget> {
final _observer = RxNotifier();
@override
void initState() {
super.initState();
// RxNotifier 混入了 NotifyManager,此处调用的是 NotifyManager$listen()
// 当接收到事件时触发 setState() 重新 build()
subs = _observer.listen(_updateTree, cancelOnError: false);
}
void _updateTree(_) {
if (mounted) {
setState(() {});
}
}
@override
void dispose() {
//移除 RxNotifier 监听
subs.cancel();
//实际调用 NotifyManager.close,移除对 .obx 的监听。
_observer.close();
super.dispose();
}
@override
Widget build(BuildContext context) => RxInterface.notifyChildren(_observer, widget.build);
}
dart
abstract class RxInterface<T> {
static RxInterface? proxy;
// observer 为 ObxWidget 创建的 RxNotifier
// 方法宗旨为将最新 observer 赋值给 proxy
static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) {
final oldObserver = RxInterface.proxy;
RxInterface.proxy = observer;
final result = builder();
if (!observer.canUpdate) {
RxInterface.proxy = oldObserver;
throw """....""";
}
RxInterface.proxy = oldObserver;
return result;
}
}
dart
//controller.count.value 即调用 RxInt.value,实际调用到 RxObjectMixin$value()
abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> {}
mixin RxObjectMixin<T> on NotifyManager<T> {
T get value {
//注册 ObxWidget 创建的 RxNotifier 监听,将 .obx 时创建的 GetStream 作为监听处理。
// addListener() 实际调用的 NotifyManager$addListener()
RxInterface.proxy?.addListener(subject);
//返回 .obx 时初始化的值
return _value;
}
}
dart
class RxNotifier<T> = RxInterface<T> with NotifyManager<T>;
mixin NotifyManager<T> {
final _subscriptions = <GetStream, List<StreamSubscription>>{};
//rxGetx 为 .box 时创建的 GetStream
//subject 为 ObxWidget 时创建的 GetStream
// 由此实现数据变动消息转换,.obx 数据变动 -> ObxWidget
void addListener(GetStream<T> rxGetx) {
if (!_subscriptions.containsKey(rxGetx)) {
final subs = rxGetx.listen((data) {
if (!subject.isClosed) subject.add(data);
});
final listSubscriptions = _subscriptions[rxGetx] ??= <StreamSubscription>[];
listSubscriptions.add(subs);
}
}
//移除所有 GetStream 监听
void close() {
_subscriptions.forEach((getStream, subscriptions) {
for (final subscription in subscriptions) {
subscription.cancel();
}
});
_subscriptions.clear();
subject.close();
}
}
小结
- Obx 对应 ObxWidget,内部创建了一个 RxNotifier 对象,RxNotifier 混入了 NotifyManager,所以也创建了一个 GetStream。
- ObxWidget 在 initState() 阶段添加了对 RxNotifier 对象的监听,如果有事件则触发 setState() 刷新 ObxWidget。
- ObxWidget 在 build() 阶段除了加载页面,还将 RxNotifier 赋值给 RxInterface.proxy。
- 若在 Obx() 中(即 build() 阶段)使用了 .obx 值,实际执行 _RxImpl$get value(),其调用 RxInterface.proxy.addListener()(即 RxNotifier.addListener())将 _RxImpl 持有的 Stream 传入。addListener() 具体实现在 NotifyManager 中,内部逻辑为添加传入的 _RxImpl 的 Stream 监听,如果有事件则调用 RxNotifier.add() 转发事件。
- ObxWidget 在 dispose() 阶段移除 RxNotifier 对象的监听,并移除对所有 _RxImpl 的 GetStream 的监听。
Update
示例:
var count = 0.obx;
count++;
dart
abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> {}
mixin RxObjectMixin<T> on NotifyManager<T> {
// count++ 最终调用 set value()
set value(T val) {
if (subject.isClosed) return;
sentToStream = false;
if (_value == val && !firstRebuild) return;
firstRebuild = false;
//赋值
_value = val;
sentToStream = true;
//通知 .obx 的 GetStream 数据变动
subject.add(_value);
}
}
小结
修改 .obx 值,即调用 _RxImpl$set value() 方法,更新数据,并调用其持有的 GetStream 的 add() 发送事件。结合 ObxWidget 中的监听,该事件最终转发到 ObxWidget 触发 setState() 刷新页面。
小结
- .obx (即 Rx<\T>) 的作用:
- 设置初始默认值。
- 创建一个 GetStream 用于后续状态通知 (Rx mixin NotifyManager)。
- 提供 get value() 方法,其内部调用 RxInterface.proxy 持有的 RxNotifier 对象的 addListener() 注册监听。具体实现在 NotifyManager 中,内部监听传入的 GetStream,当有事件时调用 RxNotifier$add() 触发它的监听。
- 提供 set value() 方法,更新值,并发送 GetStream 事件。
- ObxWidget 的作用:
- 创建 RxNotifier(mixin NotifyManager) 对象,并监听其变化(GetStream),如果有事件则触发 setState() 刷新页面(即执行注入的 build() 方法)。
- 在 build() 中将创建的 RxNotifier 对象赋值给 RxInterface.proxy,并执行一次页面加载。
- 注入的 build() 中如果使用了 .obx,即调用了 .obx 的 get value,此时建立了 ObxWidget RxNotifier 与 .obx GetStream 间的关联。
- .obx 更新触发 ObxWidget 刷新的流程:
总结
- GetX 的状态管理方案,主要利用 Dart 的 mixin 来实现状态的传递,即监听者与被监听着都混入同一个 mixin。
- GetBuilder 是 GetX 提供的轻量状态管理方式,必须依赖 GetxController 。GetBuilder 与 GetxController 都混入 ListNotifierMixin 类,其提供了注册监听和发送事件,即实现了 GetxController 内发生数据变动,GetBuilder 感知并触发 build()。但需要注意 GetBuilder 的刷新范围,因为 GetxController 中只要执行了 update()(没有带 id),则会触发所有 GetBuilder 刷新,如果与状态无关的页面过多,会浪费资源。
- Obx 是 GetX 提供的响应式状态管理方式,非必需 GetxController。.obx 与 ObxWidget 都混入了 NotifyManager,其内部实现了 .obx Stream 中的事件转发至 ObxWidget Stream 的逻辑,即实现了 .obx 数据变动,ObxWidget 感知并触发 build()。该方式使用简单,并且自行控制刷新范围,但由于使用 Stream 方式对资源消耗相对 GetBuilder 要多一些。